package com.boatAnchorAssistant.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boatAnchorAssistant.pojo.entity.*;
import com.boatAnchorAssistant.pojo.enums.device.DeviceTypeEnum;
import com.boatAnchorAssistant.pojo.param.device.*;
import com.boatAnchorAssistant.pojo.vo.device.*;
import com.boatAnchorAssistant.pojo.dto.device.*;
import com.boatAnchorAssistant.service.check.ClassUtil;
import com.boatAnchorAssistant.service.config.FixedValueConfig;
import com.boatAnchorAssistant.service.repository.in.*;
import com.boatAnchorAssistant.service.service.in.DeviceService;
import nirvana.core.context.WebContext;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.exceptions.BizException;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 【描 述】：设备服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    private final DeviceRepository deviceRepository;
    private final DataDictionaryRepository dataDictionaryRepository;
    private final ClassUtil<Device> classUtil;
    private final UserCollectRepository userCollectRepository;
    private final UserDataDictionaryRepository userDataDictionaryRepository;
    private final UserRepository userRepository;


    public DeviceServiceImpl(DeviceRepository deviceRepository, DataDictionaryRepository dataDictionaryRepository, ClassUtil<Device> classUtil, UserCollectRepository userCollectRepository, UserDataDictionaryRepository userDataDictionaryRepository, UserRepository userRepository) {
        this.deviceRepository = deviceRepository;
        this.dataDictionaryRepository = dataDictionaryRepository;
        this.classUtil = classUtil;
        this.userCollectRepository = userCollectRepository;
        this.userDataDictionaryRepository = userDataDictionaryRepository;
        this.userRepository = userRepository;
    }

    void check(Boolean isSave, Device entity){
        try {
            if (isSave) {
                classUtil.addIsHave(entity, deviceRepository);
            } else {
                classUtil.updateIsHave(entity, deviceRepository,entity.getId());
            }
        }
        catch (Exception e){
            e.printStackTrace();
            throw new BizException(e.getMessage());
        }
    }


    /**
     * 创建设备
     *
     * @param param
     */
    @Override
    public void createDevice(CreateDeviceParam param) {
        Device device = new Device();
        BeanUtils.copyProperties(param, device);
        check(true,device);
        Long id = IdGenerator.SNOW.generate();
        device.setId(id);
        device.setSource(DeviceTypeEnum.CREATE);
        deviceRepository.create(device);
    }

    /**
     * 修改设备
     *
     * @param param
     */
    @Override
    public void editDevice(EditDeviceParam param) {
        Long id = param.getId();
        Device device = deviceRepository.getByIdCheck(id);
        BeanUtils.copyProperties(param, device);
        check(false,device);
        deviceRepository.edit(device);
    }

    /**
     * 移除设备
     *
     * @param id
     */
    @Override
    public void removeDevice(Long id) {
        deviceRepository.removeById(id);
    }

    /**
     * 启动/禁用设备
     *
     * @param id
     */
    @Override
    public void enabledDevice(Long id) {
        Device device = deviceRepository.getByIdCheck(id);
        device.setIsDisable(!device.getIsDisable());
        deviceRepository.edit(device);
    }

    /**
     * 获取设备详情
     *
     * @param id
     * @return
     */
    @Override
    public GetDeviceVo getDevice(Long id) {
        Device device = deviceRepository.getByIdCheck(id);
        GetDeviceVo vo = new GetDeviceVo();
        BeanUtils.copyProperties(device, vo);
        if (device.getBrandId() != null) {
            DataDictionary brand = dataDictionaryRepository.getById(device.getBrandId());
            if (brand != null) {
                vo.setBranchName(brand.getName());
            }
        }
        if (device.getAreaId() != null) {
            DataDictionary area = dataDictionaryRepository.getById(device.getAreaId());
            if (area != null) {
                vo.setAreaName(area.getName());
            }
        }
        return vo;
    }

    /**
     * 获取设备 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetDeviceListVo> getDeviceList(GetDeviceListParam param) {

        SelectDeviceDto dto = new SelectDeviceDto();
        BeanUtils.copyProperties(param, dto);

        //如果需要数据隔离的话，需要在这里设置dto的查询条件
        if (param.getIsDataSegregation()!=null && param.getIsDataSegregation()){
            Long userId= WebContext.getCurrentUserId();
            User user = userRepository.getByIdCheck(userId);
            if (!user.getIsSystem()){
                if (user.getAuthorizedType()!=null && user.getAuthorizedType()!=2){
                    List<Long> ids = userDataDictionaryRepository.selectByUserIdAndTypeId(FixedValueConfig.AREA_ID, userId);
                    if (CollectionUtil.isEmpty(ids)){
                        return new PageResult<>(new ArrayList<>(),new Page<>());
                    }
                    dto.setDataSegregationIds(ids);
                }
            }
        }

        Page<Device> page = deviceRepository.selectDevice(dto);
        List<Device> deviceList = page.getRecords();
        List<GetDeviceListVo> list = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(deviceList)) {
            Long userId= WebContext.getCurrentUserId();

            List<Long> systemConfigIds=new ArrayList<>();
            deviceList.stream().forEach(device -> {
                systemConfigIds.add(device.getBrandId());
                systemConfigIds.add(device.getAreaId());
            });

            Map<Long,Long> collectMap=new HashMap<>();
            if (param.getIsCollect()!=null && param.getIsCollect()){
                UserCollect userCollect=new UserCollect();
                userCollect.setUserId(userId);
                List<UserCollect> listByEntity = userCollectRepository.getListByEntity(userCollect);
                if (CollectionUtil.isNotEmpty(listByEntity)){
                    listByEntity.forEach(v->{
                        collectMap.put(v.getDeviceId(),v.getUserId());
                    });
                }
            }

            Map<Long, DataDictionary> map = dataDictionaryRepository.getMap(systemConfigIds);

            for (Device device : deviceList) {
                GetDeviceListVo vo = new GetDeviceListVo();
                BeanUtils.copyProperties(device, vo);
                vo.setIsCollect(false);

                if (CollectionUtil.isNotEmpty(map)){
                    DataDictionary brand = map.get(device.getBrandId());
                    if (brand != null) {
                        vo.setBranchName(brand.getName());
                    }
                    DataDictionary area = map.get(device.getAreaId());
                    if (area != null) {
                        vo.setAreaName(area.getName());
                    }
                    if (param.getIsCollect()!=null && param.getIsCollect()){
                        if (collectMap.containsKey(device.getId())){
                            vo.setIsCollect(true);
                        }
                    }
                }
                list.add(vo);
            }
        }
        return new PageResult<>(list, page);

    }

    /**
     * 获取设备下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetDeviceDownListVo> getDeviceDownList(GetDeviceDownListParam param) {
        List<GetDeviceDownListVo> list = new ArrayList<>();

        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getIsDisable, false);

        //数据隔离
        if (param.getIsDataSegregation()!=null && param.getIsDataSegregation()){
            Long userId= WebContext.getCurrentUserId();
            User user = userRepository.getByIdCheck(userId);
            if (!user.getIsSystem()){
                if (user.getAuthorizedType()!=null && user.getAuthorizedType()!=2){
                    List<Long> ids = userDataDictionaryRepository.selectByUserIdAndTypeId(FixedValueConfig.AREA_ID, userId);
                    if (CollectionUtil.isNotEmpty(ids)){
                        wrapper.in(Device::getAreaId,ids);
                    }else{
                        return list;
                    }
                }
            }
        }
        List<Device> deviceList = deviceRepository.getBaseMapper().selectList(wrapper);

        if (CollectionUtil.isNotEmpty(deviceList)){
            List<Long> systemConfigIds=new ArrayList<>();
            deviceList.stream().forEach(device -> {
                systemConfigIds.add(device.getAreaId());
            });

            Map<Long,Long> collectMap=new HashMap<>();
            if (param.getIsCollect()!=null && param.getIsCollect()){
                UserCollect userCollect=new UserCollect();
                userCollect.setUserId(WebContext.getCurrentUserId());
                List<UserCollect> listByEntity = userCollectRepository.getListByEntity(userCollect);
                if (CollectionUtil.isNotEmpty(listByEntity)){
                    listByEntity.forEach(v->{
                        collectMap.put(v.getDeviceId(),v.getUserId());
                    });
                }
            }

            Map<Long, DataDictionary> map = dataDictionaryRepository.getMap(systemConfigIds);
            for (Device device : deviceList) {
                GetDeviceDownListVo vo = new GetDeviceDownListVo();
                BeanUtils.copyProperties(device, vo);
                DataDictionary area = map.get(device.getAreaId());
                if (area != null) {
                    vo.setAreaName(area.getName());
                }

                if (param.getIsCollect()!=null && param.getIsCollect()){
                    if (collectMap.containsKey(device.getId())){
                        vo.setIsCollect(true);
                    }else{
                        vo.setIsCollect(false);
                    }
                }
                list.add(vo);
            }
        }
        return list;
    }


}



